package com.zksite.nator.client.processor;

import java.util.List;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.zksite.nator.client.config.MappingConfig;
import com.zksite.nator.client.server.initialzer.ForwardInitializer;
import com.zksite.nator.common.config.Application;
import com.zksite.nator.common.processor.RequestProcessor;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.ReferenceCountUtil;

@Component
public class DefaultForwardRequestProcessor implements RequestProcessor {

	private static final String AUTHORED = "HTTP/1.1 200 Connection established\r\n\r\n";

	private static final Logger LOGGER = LoggerFactory.getLogger(DefaultForwardRequestProcessor.class);

	@Autowired
	private MappingConfig mappingConfig;

	public boolean process(ChannelHandlerContext ctx, final Object msg) {
		HttpRequest request = (HttpRequest) msg;
		HttpHeaders headers = request.headers();
		String forwardid = headers.get("forwardid");
		if (forwardid == null) {
			return false;
		}
		if (request.method().name().equals(HttpMethod.CONNECT)) {
			ctx.writeAndFlush(AUTHORED.getBytes());
		} else {
			String string = headers.get("host");
			if (string == null) {
				return false;
			}
			String[] split = string.split(":");
			if (LOGGER.isDebugEnabled()) {
				List<Entry<String, String>> entries = headers.entries();
				LOGGER.debug("-----------------------------------");
				for (Entry<String, String> entry : entries) {
					LOGGER.debug(entry.getKey() + ":" + entry.getValue());
				}
				LOGGER.debug("-----------------------------------");
			}
			Application application = mappingConfig.getApplication(split[0]);
			if (application == null) {
				ctx.writeAndFlush(createNotFound());
				return false;
			}
			// 连接至目标服务器
			Bootstrap bootstrap = new Bootstrap();
			bootstrap.group(ctx.channel().eventLoop()) // 注册线程池
					.channel(ctx.channel().getClass()) // 使用NioSocketChannel来作为连接用的channel类
					.handler(new ForwardInitializer(ctx.channel(), forwardid));

			ChannelFuture cf = bootstrap.connect(application.getHost(), Integer.valueOf(application.getPort()));
			cf.addListener(new ChannelFutureListener() {
				public void operationComplete(ChannelFuture future) throws Exception {
					if (future.isSuccess()) {
						future.channel().writeAndFlush(msg);
					} else {
						future.channel().close();
					}
				}
			});
		}
		return false;
	}

	public HttpResponse createNotFound() {
		byte[] content = "404".getBytes();
		HttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND,
				Unpooled.wrappedBuffer(content));
		response.headers().add("Content-Length", content.length);
		return response;
	}

}
